using System;
using System.Collections.Generic;
using System.Text;
using System.IO.Ports;
using System.Threading;

namespace KNCApp.Port
{
  
    public class PortHandler
    {
        private bool isRunning;
        private SerialPort serialPort;
        private string startStr = "";

        private Thread readThread;

        public PortHandler(SerialPort sp)
        {
            serialPort = sp;
            init();
        }

        public PortHandler(string portName)
        {
            serialPort = new SerialPort(portName);
            init();
        }

        public static bool IsPortAvailable(string portName)
        {
            string[] ports = SerialPort.GetPortNames();
            foreach (string p in ports)
            {
                if (p == portName)
                    return true;
            }
            return false;
        }

        private void init()
        {
            serialPort.ReadTimeout = 500;
            serialPort.WriteTimeout = 500;
            BaudRate = 9600;
            Parity = Parity.None;
            DataBits = 8;
            StopBits = StopBits.One;
            Handshake = Handshake.XOnXOff;
        }

        public void StartReading(string startStr, IReceiver receiver)
        {
            this.startStr = startStr;
            bool openOK = true;
            if (isRunning)
            {
                return;
            }
            readThread = new Thread(read);
            try
            {
                if (!serialPort.IsOpen)
                {
                    serialPort.Open();
                }
            }
            catch (Exception ex)
            {
                Program.LogError(ex.ToString());
                openOK = false;
            }
            if (openOK)
            {
                isRunning = true;
                readThread.Start(receiver);
            }
        }

        public void read(object recObj)
        {
            string str = "";
            bool initOK = true;
            Thread.CurrentThread.Priority = ThreadPriority.BelowNormal;
            if (startStr != null && startStr.Length > 0)
            {
                int cnt = 0;
                initOK = false;
                while (cnt < 10)
                {
                    try
                    {
                        serialPort.WriteLine(startStr);
                        str = serialPort.ReadLine();
                        if (str == startStr)
                        {
                            initOK = true;
                            break;
                        }
                    }
                    catch (TimeoutException)
                    {

                    }
                    cnt++;
                }
            }
            if (!initOK)
            {
                Program.LogError("Brak komunikacji na porcie " + serialPort.PortName);
                isRunning = false;
                return;
            }
            
            while (isRunning)
            {
                try
                {
                    lock (serialPort)
                    {
                        if (serialPort.IsOpen)
                        {
                            str = serialPort.ReadLine();
                        }
                    }
                    IReceiver rec = recObj as IReceiver;
                    if (rec != null)
                    {
                        rec.Receive(str);
                    }
                }
                catch (TimeoutException)
                { 

                }
            }
        }

        public void Stop(string stopStr)
        {
            isRunning = false;
            lock (serialPort)
            {
                if (stopStr != null && stopStr.Length > 0)
                {
                    serialPort.WriteLine(stopStr);
                }
                serialPort.Close();
            }
        }


        public string PortName
        {
            get { return serialPort.PortName; }
            set { serialPort.PortName = value; }
        }

        public int BaudRate
        {
            get { return serialPort.BaudRate; }
            set { serialPort.BaudRate = value; }
        }

        public Parity Parity
        {
            get { return serialPort.Parity; }
            set { serialPort.Parity = value; }
        }

        public int DataBits
        {
            get { return serialPort.DataBits; }
            set { serialPort.DataBits = value; }
        }

        public StopBits StopBits
        {
            get { return serialPort.StopBits; }
            set { serialPort.StopBits = value; }
        }

        public Handshake Handshake
        {
            get { return serialPort.Handshake; }
            set { serialPort.Handshake = value; }
        }
    }
   
/*
    public class PortHandler
    {
        private bool isRunning;
        private SerialPort serialPort;
        private IReceiver receiver;

        public PortHandler(SerialPort sp)
        {
            serialPort = sp;
            init();
        }

        public PortHandler(string portName)
        {
            serialPort = new SerialPort(portName);
            init();
        }

        public static bool IsPortAvailable(string portName)
        {
            string[] ports = SerialPort.GetPortNames();
            foreach (string p in ports)
            {
                if (p == portName)
                    return true;
            }
            return false;
        }

        private void init()
        {
            serialPort.ReadTimeout = 500;
            serialPort.WriteTimeout = 500;
            BaudRate = 9600;
            Parity = Parity.None;
            DataBits = 8;
            StopBits = StopBits.One;
            Handshake = Handshake.XOnXOff;

            serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);
        }

        public void StartReading(string startStr, IReceiver rec)
        {
            receiver = rec;
            if (isRunning)
            {
                return;
            }
            if (!serialPort.IsOpen)
            {
                serialPort.Open();
            }
            if (startStr != null && startStr.Length > 0)
            {
                serialPort.WriteLine(startStr);
            }
            isRunning = true;
        }

        private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            string str = null;
            try
            {
                lock (serialPort)
                {
                    if (serialPort.IsOpen)
                    {
                        str = serialPort.ReadLine();
                    }
                }
                if (receiver != null)
                {
                    receiver.Receive(str);
                }
            }
            catch (TimeoutException tex)
            {
            }
        }

        public void Stop()
        {
            isRunning = false;
            lock (serialPort)
            {
                serialPort.Close();
            }
        }

        public string PortName
        {
            get { return serialPort.PortName; }
            set { serialPort.PortName = value; }
        }

        public int BaudRate
        {
            get { return serialPort.BaudRate; }
            set { serialPort.BaudRate = value; }
        }

        public Parity Parity
        {
            get { return serialPort.Parity; }
            set { serialPort.Parity = value; }
        }

        public int DataBits
        {
            get { return serialPort.DataBits; }
            set { serialPort.DataBits = value; }
        }

        public StopBits StopBits
        {
            get { return serialPort.StopBits; }
            set { serialPort.StopBits = value; }
        }

        public Handshake Handshake
        {
            get { return serialPort.Handshake; }
            set { serialPort.Handshake = value; }
        }
    }
  */
}
